package server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Hashtable;

public class SimpleFTPServer {

	private static boolean DEBUG = true;
	private Socket socket;
	private Socket socketTransfert;
	private ServerSocket socketPassv;
	private BufferedReader reader;
	private BufferedWriter writer;
	private Hashtable clients;
	File currentDirectory;
	String directory;

	public SimpleFTPServer(Socket s) {
		socket = s;
		try {
			reader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			writer = new BufferedWriter(new OutputStreamWriter(
					socket.getOutputStream()));
		} catch (IOException e) {
			e.printStackTrace();
		}

		clients = new Hashtable();

		directory = "ftpcontent";

		currentDirectory = new File(directory);
		try {
			clients = PropertiesFTP.loadProperties("./config.properties");
		} catch (IOException e) {
			System.err.println("Probleme de chargement de system properties");
		}
	}

	public synchronized void connect() {
		try {
			sendLine("220 Welcome to SimpleFTPServer ! :)");
			
			String user = "";
			String password = "";
			String response = readLine();
			
			user = response.substring(5);
			
			if (!response.startsWith("USER ")) {
				throw new IOException(
						"SimpleFTP Server received an unknown response when connecting to the FTP server: "
								+ response);
			} else if (!clients.containsKey(user)) {
				throw new IOException(
						"SimpleFTP Server received a bad login user: "
								+ response);
			} else {
				sendLine("331 Login OK");
				response = readLine();
				password = response.substring(5);
				
				if (!response.startsWith("PASS ")) {
					throw new IOException(
							"SimpleFTP Server received an unknown response when connecting to the FTP server: "
									+ response);
				} else if (!clients.get(user).equals(password)) {
					throw new IOException(
							"SimpleFTP Server received a bad password user: "
									+ response);
				} else {
					sendLine("230 Password OK");
					System.out.println("Identification OK");
				}
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public synchronized void pwd() {
		String path = currentDirectory.getPath();
		char token = '\"';

		path = path.replaceAll("\\\\", "/");
		path = path.replace(directory, "");
		if (path.equals(""))
			path = "/";
		String result = "257 " + token + path + token + "is current directory.";

		try {
			sendLine(result);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public synchronized void passv() {
		socketTransfert = null;
		String thisIp = null;
		try {
			thisIp = InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		thisIp = thisIp.replace('.', ',');
		try {
			socketPassv = new ServerSocket(2000);
			sendLine("227 Entering Passive Mode (" + thisIp + ",7,208)");
			socketTransfert = socketPassv.accept();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}

	public synchronized void list() {
		try {
			String result = "";
			String[] fileList = currentDirectory.list();
			
			BufferedWriter writerList = new BufferedWriter(
					new OutputStreamWriter(socketTransfert.getOutputStream()));
			
			sendLine("150 Opening ASCII mode data connection for file list");
			
			//token de séparation ##
			for (int i = 0; i < fileList.length; i++)
				result += fileList[i] + "##";
			
			sendLine(result, writerList);
			
			writerList.flush();
			writerList.close();
			
			socketTransfert.close();
			socketPassv.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public synchronized void stor(String fichier) {
		try {
			File f = new File("ftpcontent/"+fichier);
			
			if(!f.exists())
				f.createNewFile();
			
			BufferedInputStream readerStor = new BufferedInputStream(socketTransfert.getInputStream());
			BufferedOutputStream writerStor = new BufferedOutputStream(new FileOutputStream(f));
			String currentFileLine = "";
			
			sendLine("150 Opening ASCII mode data connection for "+fichier);
			
			byte[] buffer = new byte[4096];
	        int bytesRead = 0;
	        while ((bytesRead = readerStor.read(buffer)) != -1) {
	        	writerStor.write(buffer, 0, bytesRead);
	        }
			/*
			while((currentFileLine = readerStor.readLine()) != null) {
				writerStor.write(currentFileLine);
			}
			*/
			writerStor.flush();
			readerStor.close();
			writerStor.close();
			
			sendLine("226 Transfer complete.");
			socketTransfert.close();
			socketPassv.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	private void sendLine(String line) throws IOException {
		if (socket == null) {
			throw new IOException("SimpleFTP is not connected.");
		}
		try {
			writer.write(line + "\r\n");
			writer.flush();
			if (DEBUG) {
				System.out.println("> " + line);
			}
		} catch (IOException e) {
			socket = null;
			throw e;
		}
	}

	private void sendLine(String line, BufferedWriter bw) throws IOException {
		if (socket == null) {
			throw new IOException("SimpleFTP is not connected.");
		}
		try {
			//bw.write(line + "\r\n");
			bw.write(line);
			if (DEBUG) {
				System.out.println("> " + line);
			}
		} catch (IOException e) {
			socket = null;
			throw e;
		}
	}

	public String readLine() throws IOException {
		String line = reader.readLine();
		if (DEBUG) {
			System.out.println("< " + line);
		}
		return line;
	}
}
